<?php

namespace app\admin\controller;

use ba\Random;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use think\facade\App;
use think\facade\Db;
use Throwable;
use app\common\controller\Backend;
use app\common\library\Exports;

/**
 * 链接管理
 */
class Jumpurl extends Backend
{
    /**
     * Jumpurl模型对象
     * @var object
     * @phpstan-var \app\admin\model\Jumpurl
     */
    protected object $model;

    protected array|string $preExcludeFields = ['id', 'create_time'];

    protected array $withJoinTable = ['urlgroup'];

    protected string|array $quickSearchField = ['id'];

    public function initialize(): void
    {
        parent::initialize();
        $this->model = new \app\admin\model\Jumpurl();
    }

    /**
     * 查看
     * @throws Throwable
     */
    public function index(): void
    {
        // 如果是 select 则转发到 select 方法，若未重写该方法，其实还是继续执行 index
        if ($this->request->param('select')) {
            $this->select();
        }

        /**
         * 1. withJoin 不可使用 alias 方法设置表别名，别名将自动使用关联模型名称（小写下划线命名规则）
         * 2. 以下的别名设置了主表别名，同时便于拼接查询参数等
         * 3. paginate 数据集可使用链式操作 each(function($item, $key) {}) 遍历处理
         */
        list($where, $alias, $limit, $order) = $this->queryBuilder();
        $res = $this->model
            ->withJoin($this->withJoinTable, $this->withJoinType)
            ->alias($alias)
            ->where($where)
            ->order($order)
            ->paginate($limit)->each(function ($row) {
                $row['linkurl'] = $this->request->server('HTTP_REFERER') . '#/?access=' . $row['uuid'];
            });
        $res->visible(['urlgroup' => ['name']]);
        $this->success('', [
            'list' => $res->items(),
            'total' => $res->total(),
            'remark' => get_route_remark(),
            'serve'=>$this->request->server()
        ]);
    }
    /**
     * 若需重写查看、编辑、删除等方法，请复制 @see \app\admin\library\traits\Backend 中对应的方法至此进行重写
     */
    /**
     * 添加
     */
    public function add(): void
    {
        if ($this->request->isPost()) {
            $data = $this->request->post();
            if (!$data) {
                $this->error(__('Parameter %s can not be empty', ['']));
            }
            $data = $this->excludeFields($data);
            if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
                $data[$this->dataLimitField] = $this->auth->id;
            }
            $result = false;
            $this->model->startTrans();
            try {
                // 模型验证
                if ($this->modelValidate) {
                    $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                    if (class_exists($validate)) {
                        $validate = new $validate();
                        if ($this->modelSceneValidate) $validate->scene('add');
                        $validate->check($data);
                    }
                }
                $source_data = json_decode(file_get_contents('php://input'), true);
                $data['urlcode'] = $source_data['urlcode'];
                $data['uuid'] = Random::uuid();
                $result = $this->model->save($data);
                $this->model->commit();
            } catch (Throwable $e) {
                $this->model->rollback();
                $this->error($e->getMessage());
            }
            if ($result !== false) {
                $this->success(__('Added successfully'));
            } else {
                $this->error(__('No rows were added'));
            }
        }

        $this->error(__('Parameter error'));
    }

    /**
     * 编辑
     * @throws Throwable
     */
    public function edit(): void
    {
        $pk = $this->model->getPk();
        $id = $this->request->param($pk);
        $row = $this->model->find($id);
        if (!$row) {
            $this->error(__('Record not found'));
        }

        $dataLimitAdminIds = $this->getDataLimitAdminIds();
        if ($dataLimitAdminIds && !in_array($row[$this->dataLimitField], $dataLimitAdminIds)) {
            $this->error(__('You have no permission'));
        }

        if ($this->request->isPost()) {
            $data = $this->request->post();
            $source_data = json_decode(file_get_contents('php://input'), true);
            $data['urlcode'] = $source_data['urlcode'];
            if (!$data) {
                $this->error(__('Parameter %s can not be empty', ['']));
            }
            $data = $this->excludeFields($data);
            $result = false;
            $this->model->startTrans();
            try {
                // 模型验证
                if ($this->modelValidate) {
                    $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                    if (class_exists($validate)) {
                        $validate = new $validate();
                        if ($this->modelSceneValidate) $validate->scene('edit');
                        $data[$pk] = $row[$pk];
                        $validate->check($data);
                    }
                }
                $result = $row->save($data);
                $this->model->commit();
            } catch (Throwable $e) {
                $this->model->rollback();
                $this->error($e->getMessage());
            }
            if ($result !== false) {
                $this->success(__('Update successful'));
            } else {
                $this->error(__('No rows updated'));
            }
        }

        $this->success('', [
            'row' => $row
        ]);
    }

    /**
     * 信息导入保存
     */
    public function importcadre()
    {
        set_time_limit(0);
        ob_clean();
        $file = $this->request->post('file');
        $urlgroup_id = $this->request->post('urlgroup_id');
        if(empty($urlgroup_id)){
            $this->error('请选择分组');
        }
        if (empty($file)) {
            $this->error('请选择上传的文件');
        }
        $ext = pathinfo($file, PATHINFO_EXTENSION);//后缀
        if (!in_array($ext, ['xls', 'xlsx'])) {
            $this->error('不支持此类型文件');
        }
        if ($ext === 'xls') {
            $reader = new Xls();
        } else {
            $reader = new Xlsx();
        }
        $filePath = App::getRootPath() . 'public' . DIRECTORY_SEPARATOR . $file;
        $data = [];
        $reader->setReadDataOnly(TRUE);
        $spreadsheet = $reader->load($filePath);
        $sheet = $spreadsheet->getActiveSheet();
        $highestRow = $sheet->getHighestRow();
        $allColumn = $sheet->getHighestDataColumn(); //取得最大的列号
        $allRow = $sheet->getHighestRow(); //取得一共有多少行
        $highestColumnIndex = Coordinate::columnIndexFromString($allColumn);//最大列转换成数字
        $fileds = [
            '',
            'name',
            'urlkey'
        ];
        $field_count = count($fileds);
        for ($row = 2; $row <= $highestRow; $row++) {
            // 构建默认字段数据
            $arr_value = [
                'status' => 1,
                'type' => 'opt0',
                'create_time' => time(),
                'urlgroup_id' => $urlgroup_id,
                'uuid' => Random::uuid(),
            ];
            for ($col = 1; $col <= $field_count - 1; $col++) {
                // 'A' 对应的ASCII码十进制为 64
                // 将ASCII值转为字符
                $chr = $this->getColumnZimu($col);
                // 列转为数据库字段名
                $key = $fileds[$col] ?? $chr;
                $value = $sheet->getCell($chr . $row)->getValue();
                $value = trim($value);
                $arr_value[$key] = $value;
            }
            $data[] = $arr_value;
        }
        Db::startTrans();
        $result = $this->model->saveAll($data);
        if ($result) {
            Db::commit();
            $this->success('导入成功' . count($data) . '条数据', $data);
        } else {
            Db::rollback();
            $this->error('导入失败', $data);
        }
    }

    private function getColumnZimu($num)
    {
        if ($num >= 0 && $num < 26) {
            // 如果是 A 到 Z 之间的列，直接返回对应的字母
            return chr(65 + $num);
        } else {
            // 针对 AA、AB、AC ... ZZ 这样的列，使用类似递归的方式计算出对应的字母组合
            $result = '';
            while ($num >= 26) {
                $result .= chr(65 + ($num % 26));
                $num = intval($num / 26) - 1;
            }
            $result .= chr(65 + $num);
            return strrev($result); // 需要反转列名字母组合
        }
    }


    public function exportcadre(): void
    {
        $ids = $this->request->post('ids/a');
        if (empty($ids)) {
            $this->error('请选择要导出的记录');
        }
        ob_clean();
        $list = $this->model->whereIn('jumpurl.id', $ids)->withJoin($this->withJoinTable, $this->withJoinType)->select();
        $list->visible(['urlgroup' => ['name']]);
        $header = array(
            0 =>
                array(
                    'field' => 'id',
                    'name' => '序号',
                ),
            ['field' => 'name', 'name' => '号码'],
            ['field' => 'urlkey', 'name' => '链接地址'],
            ['field' => 'linkurl', 'name' => '跳转地址'],
        );// 表头
        $header = array_values($header);

        //$this->error('导出成功', $list);
        foreach ($list as $key => $row) {
            $row['linkurl'] = $this->request->server('HTTP_REFERER') . '#/?access=' . $row['uuid'];
            foreach ($header as $k => $v) {
                $data[$key][$v['field']] = is_array($row[$v['field']]) ? implode(',', $row[$v['field']]) : $row[$v['field']];
            }
            $data[$key]['id'] = $key + 1;
            $data[$key] = array_values($data[$key]);
        }
        // 设置表头
        $export = new Exports(
            array_column($header, 'name'),
            $data
        );
        $file_url = $export->createTable('导出信息');
        $this->success('导出成功', [
            'document_url' =>$this->request->server('HTTP_REFERER'). $file_url
        ]);
    }
}